using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using Be.Timvw.Framework.Collections.Generic;

namespace Be.Timvw.Framework.Collections
{
    public static class NameValueCollectionHelper
    {
        private static readonly Dictionary<DuplicateKeyBehavior, Action<NameValueCollection, NameValueCollection>> duplicateKeyBehaviors;

        static NameValueCollectionHelper()
        {
            duplicateKeyBehaviors = new Dictionary<DuplicateKeyBehavior, Action<NameValueCollection, NameValueCollection>>();
            duplicateKeyBehaviors.Add(DuplicateKeyBehavior.Ignore, AddOrIgnoreOnDuplicateKey);
            duplicateKeyBehaviors.Add(DuplicateKeyBehavior.Replace, AddOrReplaceOnDuplicateKey);
            duplicateKeyBehaviors.Add(DuplicateKeyBehavior.Combine, AddOrCombineOnDuplicateKey);
            duplicateKeyBehaviors.Add(DuplicateKeyBehavior.Fail, AddOrFailOnDuplicateKey);
        }

        public static void AddOrIgnoreOnDuplicateKey(NameValueCollection collection, NameValueCollection nameValuesToAdd)
        {
            List<string> collectionKeys = GetKeys(collection);

            foreach(string key in nameValuesToAdd.Keys)
            {
                if(!collectionKeys.Contains(key))
                {
                    collection.Add(key, nameValuesToAdd.Get(key));
                }
            }
        }

        public static void AddOrReplaceOnDuplicateKey(NameValueCollection collection, NameValueCollection nameValuesToAdd)
        {
            List<string> collectionKeys = GetKeys(collection);

            foreach(string key in nameValuesToAdd.Keys)
            {
                if(collectionKeys.Contains(key))
                {
                    collection[key] = nameValuesToAdd.Get(key);
                }
                else
                {
                    collection.Add(key, nameValuesToAdd.Get(key));
                }
            }
        }

        public static void AddOrCombineOnDuplicateKey(NameValueCollection collection, NameValueCollection nameValuesToAdd)
        {
            foreach(string key in nameValuesToAdd.Keys)
            {
                collection.Add(key, nameValuesToAdd.Get(key));
            }
        }

        public static void AddOrFailOnDuplicateKey(NameValueCollection collection, NameValueCollection nameValuesToAdd)
        {
            List<string> collectionKeys = GetKeys(collection);

            foreach(string key in nameValuesToAdd.Keys)
            {
                if(collectionKeys.Contains(key))
                {
                    throw new ArgumentException(string.Format("The collection already contains a NameValue pair with name {0}.", key));
                }
                
                collection.Add(key, nameValuesToAdd.Get(key));
            }
        }

        public static void Add(NameValueCollection collection, NameValueCollection nameValuesToAdd, DuplicateKeyBehavior duplicateKeyBehavior)
        {
            duplicateKeyBehaviors[duplicateKeyBehavior](collection, nameValuesToAdd);
        }

        private static List<string> GetKeys(NameObjectCollectionBase collection)
        {
            return new List<string>(EnumerableHelper.Convert<string>(collection.Keys));
        }
    }
}